package com.xiyuan.smartutils.comparator;

import com.xiyuan.smartutils.Objects;
import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.constants.AsciiConstants;

import java.io.Serializable;
import java.util.Comparator;

/**
 * 版本比较器<br>
 * 比较两个版本的大小<br>
 * 排序时版本从小到大排序，即比较时小版本在前，大版本在后<br>
 * 支持如：1.3.20.8，6.82.20160101，8.5a/8.5c等版本形式<br>
 *
 * @author xiyuan-lgz 2024-07-20 @version v1.0.0 新建与整理
 */
public class VersionComparator implements Comparator<String>, Serializable, AsciiConstants {
    private static final long serialVersionUID = 8083701245147495562L;
    
    /**
     * 单例
     */
    public static final VersionComparator INSTANCE = new VersionComparator();
    
    /**
     * 默认构造
     */
    public VersionComparator() {
    }
    
    // private boolean equal(String a, String b){
    //     if (a instanceof Number && b instanceof Number) {
    //         return ((BigDecimal) a).compareTo((BigDecimal) b) == 0;
    //     }
    //
    // }
    // -----------------------------------------------------------------------------------------------------
    
    /**
     * 比较两个版本<br>
     * null版本排在最小：即：
     * <pre>
     * compare(null, "v1") &lt; 0
     * compare("v1", "v1")  = 0
     * compare(null, null)   = 0
     * compare("v1", null) &gt; 0
     * compare("1.0.0", "1.0.2") &lt; 0
     * compare("1.0.2", "1.0.2a") &lt; 0
     * compare("1.13.0", "1.12.1c") &gt; 0
     * compare("V0.0.20170102", "V0.0.20170101") &gt; 0
     * </pre>
     *
     * @param version1 版本1
     * @param version2 版本2
     */
    @Override
    public int compare(String version1, String version2) {
        if (Objects.equals(version1, version2)) {
            return 0;
        }
        if (version1 == null && version2 == null) return 0;
        
        // null视为最小版本，排在前
        if (version1 == null) {return -1;}
        if (version2 == null) return 1;
        
        final String[] v1s = StrUtils.split(version1, ".");
        final String[] v2s = StrUtils.split(version2, ".");
        
        int diff = 0;
        // 取最小长度值
        int minLength = Math.min(v1s.length, v2s.length);
        String v1;
        String v2;
        for (int i = 0; i < minLength; i++) {
            v1 = v1s[i];
            v2 = v2s[i];
            // 先比较长度
            diff = v1.length() - v2.length();
            if (0 == diff) {
                diff = v1.compareTo(v2);
            }
            
            if (diff != 0) {
                // 已有结果，结束
                return diff;
            }
        }
        
        // 如果已经分出大小，则直接返回，如果未分出大小，则再比较位数，有子版本的为大；
        return v1s.length - v2s.length;
    }
}